<template>
  <view class="game-container" :style="{ paddingTop: customBarHeight + 'px' }">
    <view class="game-header">
      <view class="header-left">
        <button class="back-btn" @tap="goBack">
          <text class="back-icon">←</text>
        </button>
      </view>
      <view class="header-center">
        <text class="level-title">第{{ currentLevel }}关</text>
      </view>
      <view class="header-right">
        <button class="reset-btn" @tap="resetLevel">
          <text class="reset-icon">↻</text>
        </button>
      </view>
    </view>

    <view class="game-board">
      <view class="map-container">
        <view v-for="(row, rowIndex) in mapGrid" :key="rowIndex" class="map-row">
          <view v-for="(cell, colIndex) in row" :key="colIndex" class="map-cell-wrapper"
            @tap="handleCellClick(colIndex, rowIndex)">
            <!-- 基础地图图片 -->
            <image :src="getBaseCellImageSrc(cell)" class="map-cell" :class="getBaseCellClass(cell)"
              :style="getCellStyle(cell)" />

            <!-- 选中箱子的叠加图标 -->
            <image v-if="selectedBox && selectedBox.x === colIndex && selectedBox.y === rowIndex"
              src="../../assets/images/box_selected.png" class="overlay-icon selected-icon" />

            <!-- 可推位置的叠加图标 -->
            <image v-if="isBoxMovePoint(colIndex, rowIndex)" src="../../assets/images/box_move_point.png"
              class="overlay-icon move-point-icon" />
          </view>
        </view>

        <!-- 独立的玩家精灵 -->
        <image :src="getPlayerImageSrc()" class="player-sprite" :class="getPlayerClass()" :style="getPlayerStyle()" />
      </view>
    </view>

    <view class="game-info">
      <text class="moves-count">步数: {{ moves }}</text>
      <text class="level-info">{{ levelData?.L_Title || '' }}</text>
    </view>
  </view>
</template>

<script>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import Taro from '@tarojs/taro'
import levelsData from '../../assets/levels/sokoban100.js'
import './game.scss'

export default {
  setup() {
    const customBarHeight = ref(0)
    const currentLevel = ref(1)
    const levelData = ref(null)
    const mapGrid = ref([])
    const moves = ref(0)
    const playerPos = ref({ x: 0, y: 0 })
    const playerDirection = ref('down')
    const isMoving = ref(false)
    const isOnTarget = ref(false)
    const selectedBox = ref(null)  // 选中的箱子位置 {x, y}
    const boxMovePoints = ref([])  // 箱子可移动的点列表 [{x, y}]
    const isLevelComplete = ref(false)  // 关卡是否通关

    onMounted(() => {
      const systemInfo = Taro.getSystemInfoSync();
      const statusBarHeight = systemInfo.statusBarHeight;
      customBarHeight.value = statusBarHeight + 44 // 44 是导航栏高度
      // 获取路由参数中的关卡号
      const params = Taro.getCurrentInstance().router.params
      if (params.level) {
        currentLevel.value = parseInt(params.level)
      }

      // 加载关卡数据
      loadLevel(currentLevel.value)
    })

    const loadLevel = (levelId) => {
      const level = levelsData.find(l => l.L_id === levelId)
      if (level) {
        levelData.value = level
        parseMapData(level.L_thin_XSB)
        moves.value = 0
        isMoving.value = false
        selectedBox.value = null
        boxMovePoints.value = []
        isLevelComplete.value = false
      } else {
        console.error('Level not found:', levelId)
      }
    }

    const parseMapData = (mapString) => {
      const lines = mapString.split('\n')
      const grid = []
      let maxWidth = 0

      // 找到最大宽度
      lines.forEach(line => {
        if (line.length > maxWidth) {
          maxWidth = line.length
        }
      })

      // 解析每一行
      lines.forEach((line, rowIndex) => {
        const row = []
        for (let colIndex = 0; colIndex < maxWidth; colIndex++) {
          const char = line[colIndex] || '_'
          const cell = {
            type: getBaseCellType(char),
            char: char,
            x: colIndex,
            y: rowIndex
          }

          // 记录玩家位置和状态
          if (char === '@' || char === '+') {
            playerPos.value = { x: colIndex, y: rowIndex }
            isOnTarget.value = char === '+'
            // 将玩家位置设为地板或目标
            cell.type = char === '+' ? 'target' : 'floor'
            cell.char = char === '+' ? '.' : '-'
          }

          row.push(cell)
        }
        grid.push(row)
      })

      mapGrid.value = grid
    }

    const getBaseCellType = (char) => {
      switch (char) {
        case '#': return 'wall'
        case '$': return 'box'
        case '.': return 'target'
        case '@': return 'floor'  // 玩家位置显示为地板
        case '+': return 'target' // 玩家在目标上，显示目标
        case '*': return 'boxOnTarget'
        case '-': return 'floor'
        case '_': return 'floor'
        default: return 'floor'
      }
    }

    // 检查坐标是否可通行（玩家可以移动到的位置）
    const isWalkable = (x, y) => {
      if (x < 0 || y < 0 || y >= mapGrid.value.length || x >= mapGrid.value[0].length) {
        return false
      }

      const cell = mapGrid.value[y][x]
      // 地板和目标是可通行的，墙体和箱子不可通行
      return cell.type === 'floor' || cell.type === 'target'
    }

    // 检查位置是否有箱子
    const hasBox = (x, y) => {
      if (x < 0 || y < 0 || y >= mapGrid.value.length || x >= mapGrid.value[0].length) {
        return false
      }
      const cell = mapGrid.value[y][x]
      return cell.type === 'box' || cell.type === 'boxOnTarget'
    }

    // 检查坐标是否可以放置箱子（没有墙体、没有其他箱子）
    const canPlaceBox = (x, y) => {
      if (x < 0 || y < 0 || y >= mapGrid.value.length || x >= mapGrid.value[0].length) {
        return false
      }
      const cell = mapGrid.value[y][x]
      return cell.type === 'floor' || cell.type === 'target'
    }

    // 计算箱子可以被推到的所有位置（全局可达性算法）
    const calculateBoxMovePoints = (boxX, boxY) => {
      const movePoints = []
      const visited = new Set()
      const queue = [{ x: boxX, y: boxY }]

      visited.add(`${boxX},${boxY}`)

      const directions = [
        { x: 0, y: -1 }, // 上
        { x: 1, y: 0 },  // 右
        { x: 0, y: 1 },  // 下
        { x: -1, y: 0 }  // 左
      ]

      // 检查位置是否可以放置箱子（忽略当前选中的箱子）
      const canPlaceBoxIgnoreCurrent = (x, y) => {
        if (x < 0 || y < 0 || y >= mapGrid.value.length || x >= mapGrid.value[0].length) {
          return false
        }
        const cell = mapGrid.value[y][x]
        // 如果是当前选中的箱子位置，认为可以通过
        if (x === boxX && y === boxY) {
          return true
        }
        return cell.type === 'floor' || cell.type === 'target'
      }

      // 检查玩家是否能到达指定位置（忽略当前选中的箱子）
      const canPlayerReach = (targetX, targetY) => {
        if (!canPlaceBoxIgnoreCurrent(targetX, targetY)) {
          return false
        }

        const pathQueue = [{ x: playerPos.value.x, y: playerPos.value.y, path: [] }]
        const pathVisited = new Set()
        pathVisited.add(`${playerPos.value.x},${playerPos.value.y}`)

        while (pathQueue.length > 0) {
          const current = pathQueue.shift()

          if (current.x === targetX && current.y === targetY) {
            return true
          }

          for (const dir of directions) {
            const newX = current.x + dir.x
            const newY = current.y + dir.y
            const key = `${newX},${newY}`

            if (!pathVisited.has(key) && canPlaceBoxIgnoreCurrent(newX, newY)) {
              pathQueue.push({ x: newX, y: newY })
              pathVisited.add(key)
            }
          }
        }

        return false
      }

      // BFS探索所有可推送位置
      while (queue.length > 0) {
        const currentBox = queue.shift()

        // 检查四个方向
        for (const dir of directions) {
          const newBoxX = currentBox.x + dir.x
          const newBoxY = currentBox.y + dir.y
          const playerPushX = currentBox.x - dir.x  // 玩家推箱时需要站的位置
          const playerPushY = currentBox.y - dir.y

          const newBoxKey = `${newBoxX},${newBoxY}`

          // 检查新位置是否已访问过
          if (visited.has(newBoxKey)) {
            continue
          }

          // 检查新位置是否可以放置箱子
          if (!canPlaceBoxIgnoreCurrent(newBoxX, newBoxY)) {
            continue
          }

          // 检查玩家推箱位置是否可以到达
          if (!canPlayerReach(playerPushX, playerPushY)) {
            continue
          }

          // 这个位置可以推到
          visited.add(newBoxKey)

          // 只有不是起始位置才加入移动点
          if (!(newBoxX === boxX && newBoxY === boxY)) {
            movePoints.push({ x: newBoxX, y: newBoxY })
          }

          queue.push({ x: newBoxX, y: newBoxY })
        }
      }

      return movePoints
    }

    // 选择箱子
    const selectBox = (x, y) => {
      if (hasBox(x, y)) {
        // 如果点击的是已选中的箱子，取消选择
        if (selectedBox.value && selectedBox.value.x === x && selectedBox.value.y === y) {
          selectedBox.value = null
          boxMovePoints.value = []
        } else {
          // 选择新箱子
          selectedBox.value = { x, y }
          boxMovePoints.value = calculateBoxMovePoints(x, y)
        }
        return true
      }
      return false
    }

    // 检查关卡是否通关（所有箱子都在目标位置）
    const checkLevelComplete = () => {
      for (let y = 0; y < mapGrid.value.length; y++) {
        for (let x = 0; x < mapGrid.value[y].length; x++) {
          const cell = mapGrid.value[y][x]
          if (cell.type === 'box') {
            // 还有箱子不在目标位置
            return false
          }
        }
      }
      return true
    }

    // 跨端存储写入
    const setStorageSync = (key, value) => {
      if (Taro.setStorageSync && typeof Taro.setStorageSync === 'function') {
        Taro.setStorageSync(key, value)
      } else if (typeof window !== 'undefined' && window.localStorage) {
        window.localStorage.setItem(key, typeof value === 'string' ? value : JSON.stringify(value))
      }
    }

    // 跨端存储读取
    const getStorageSync = (key) => {
      if (Taro.getStorageSync && typeof Taro.getStorageSync === 'function') {
        return Taro.getStorageSync(key)
      } else if (typeof window !== 'undefined' && window.localStorage) {
        const value = window.localStorage.getItem(key)
        try {
          return JSON.parse(value)
        } catch (e) {
          return value
        }
      }
      return null
    }

    // 处理通关
    const handleLevelComplete = async () => {
      isLevelComplete.value = true

      // 保存当前关卡进度
      setStorageSync('currentLevel', currentLevel.value + 1)

      // 保存已完成关卡
      const completedLevels = getStorageSync('completedLevels') || []
      if (!completedLevels.includes(currentLevel.value)) {
        completedLevels.push(currentLevel.value)
        setStorageSync('completedLevels', completedLevels)
      }

      // 显示通关提示
      await Taro.showToast({
        title: '恭喜通关！',
        icon: 'success',
        duration: 2000
      })

      // 检查是否是最后一关
      const totalLevels = levelsData.length
      if (currentLevel.value >= totalLevels) {
        // 最后一关，显示完成提示
        await Taro.showModal({
          title: '游戏完成',
          content: '恭喜您完成了所有关卡！',
          showCancel: false,
          confirmText: '返回主页'
        })

        Taro.redirectTo({
          url: '/pages/index/index'
        })
      } else {
        // 自动进入下一关
        setTimeout(() => {
          currentLevel.value++
          loadLevel(currentLevel.value)
        }, 2000)
      }
    }

    // 检查位置是否是箱子的可移动点
    const isBoxMovePoint = (x, y) => {
      return boxMovePoints.value.some(point => point.x === x && point.y === y)
    }

    // 计算箱子从当前位置到目标位置的推箱路径
    const calculatePushPath = (boxFromX, boxFromY, boxToX, boxToY) => {
      // 使用BFS找到箱子的移动路径
      const queue = [{ x: boxFromX, y: boxFromY, path: [] }]
      const visited = new Set()
      visited.add(`${boxFromX},${boxFromY}`)

      const directions = [
        { x: 0, y: -1, name: 'up' },    // 上
        { x: 1, y: 0, name: 'right' },  // 右
        { x: 0, y: 1, name: 'down' },   // 下
        { x: -1, y: 0, name: 'left' }   // 左
      ]

      // 检查位置是否可以放置箱子（临时忽略起始箱子）
      const canPlaceBoxTemp = (x, y) => {
        if (x < 0 || y < 0 || y >= mapGrid.value.length || x >= mapGrid.value[0].length) {
          return false
        }
        const cell = mapGrid.value[y][x]
        // 如果是起始位置，认为可以通过
        if (x === boxFromX && y === boxFromY) {
          return true
        }
        return cell.type === 'floor' || cell.type === 'target'
      }

      // 检查玩家是否能到达推箱位置（临时忽略起始箱子）
      const canPlayerReachTemp = (targetX, targetY) => {
        const pathQueue = [{ x: playerPos.value.x, y: playerPos.value.y }]
        const pathVisited = new Set()
        pathVisited.add(`${playerPos.value.x},${playerPos.value.y}`)

        while (pathQueue.length > 0) {
          const current = pathQueue.shift()

          if (current.x === targetX && current.y === targetY) {
            return true
          }

          for (const dir of directions) {
            const newX = current.x + dir.x
            const newY = current.y + dir.y
            const key = `${newX},${newY}`

            if (!pathVisited.has(key) && canPlaceBoxTemp(newX, newY)) {
              pathQueue.push({ x: newX, y: newY })
              pathVisited.add(key)
            }
          }
        }

        return false
      }

      while (queue.length > 0) {
        const current = queue.shift()

        if (current.x === boxToX && current.y === boxToY) {
          return current.path
        }

        for (const dir of directions) {
          const newBoxX = current.x + dir.x
          const newBoxY = current.y + dir.y
          const playerPushX = current.x - dir.x  // 玩家推箱时需要站的位置
          const playerPushY = current.y - dir.y

          const newBoxKey = `${newBoxX},${newBoxY}`

          if (visited.has(newBoxKey)) {
            continue
          }

          // 检查新位置是否可以放置箱子
          if (!canPlaceBoxTemp(newBoxX, newBoxY)) {
            continue
          }

          // 检查玩家推箱位置是否可达
          if (!canPlayerReachTemp(playerPushX, playerPushY)) {
            continue
          }

          visited.add(newBoxKey)
          const newPath = [...current.path, {
            boxFrom: { x: current.x, y: current.y },
            boxTo: { x: newBoxX, y: newBoxY },
            direction: dir.name
          }]

          queue.push({ x: newBoxX, y: newBoxY, path: newPath })
        }
      }

      return null // 无路径
    }

    // BFS寻路算法
    const findPath = (startX, startY, endX, endY) => {
      if (!isWalkable(endX, endY)) {
        return null
      }

      if (startX === endX && startY === endY) {
        return []
      }

      const queue = [{ x: startX, y: startY, path: [] }]
      const visited = new Set()
      visited.add(`${startX},${startY}`)

      const directions = [
        { x: 0, y: -1 }, // 上
        { x: 1, y: 0 },  // 右
        { x: 0, y: 1 },  // 下
        { x: -1, y: 0 }  // 左
      ]

      while (queue.length > 0) {
        const current = queue.shift()

        for (const dir of directions) {
          const newX = current.x + dir.x
          const newY = current.y + dir.y
          const key = `${newX},${newY}`

          if (!visited.has(key) && isWalkable(newX, newY)) {
            const newPath = [...current.path, { x: newX, y: newY }]

            if (newX === endX && newY === endY) {
              return newPath
            }

            queue.push({ x: newX, y: newY, path: newPath })
            visited.add(key)
          }
        }
      }

      return null // 无路径
    }

    // 获取移动方向
    const getDirection = (fromX, fromY, toX, toY) => {
      const dx = toX - fromX
      const dy = toY - fromY

      if (Math.abs(dx) > Math.abs(dy)) {
        return dx > 0 ? 'right' : 'left'
      } else {
        return dy > 0 ? 'down' : 'up'
      }
    }

    // 执行移动动画
    const executeMove = async (path) => {
      if (path.length === 0) return

      isMoving.value = true

      // 只在开始和结束时更新方向，中间过程保持流畅移动
      for (let i = 0; i < path.length; i++) {
        const step = path[i]
        const prevPos = i === 0 ? playerPos.value : path[i - 1]

        // 更新玩家方向
        playerDirection.value = getDirection(prevPos.x, prevPos.y, step.x, step.y)

        // 更新玩家位置（不更新地图状态）
        playerPos.value = { x: step.x, y: step.y }

        // 检查是否在目标上
        const cell = mapGrid.value[step.y][step.x]
        isOnTarget.value = cell.type === 'target'

        // 动画延迟
        await new Promise(resolve => setTimeout(resolve, 20))
      }
      moves.value++
      isMoving.value = false
    }

    // 推箱子动画（支持连续推箱）
    const executePushBox = async (boxFromX, boxFromY, boxToX, boxToY) => {
      isMoving.value = true

      // 计算推箱路径
      const pushPath = calculatePushPath(boxFromX, boxFromY, boxToX, boxToY)
      if (!pushPath || pushPath.length === 0) {
        isMoving.value = false
        return
      }

      // 当前箱子位置（会在循环中更新）
      let currentBoxX = boxFromX
      let currentBoxY = boxFromY

      // 逐步执行每个推箱动作
      for (const step of pushPath) {
        // 计算玩家需要到达的推箱位置
        const pushX = step.boxFrom.x + (step.boxFrom.x - step.boxTo.x)
        const pushY = step.boxFrom.y + (step.boxFrom.y - step.boxTo.y)

        // 玩家移动到推箱位置
        const playerPath = findPath(playerPos.value.x, playerPos.value.y, pushX, pushY)
        if (playerPath && playerPath.length > 0) {
          for (let i = 0; i < playerPath.length; i++) {
            const pathStep = playerPath[i]
            const prevPos = i === 0 ? playerPos.value : playerPath[i - 1]

            playerDirection.value = getDirection(prevPos.x, prevPos.y, pathStep.x, pathStep.y)
            playerPos.value = { x: pathStep.x, y: pathStep.y }

            const cell = mapGrid.value[pathStep.y][pathStep.x]
            isOnTarget.value = cell.type === 'target'

            await new Promise(resolve => setTimeout(resolve, 80))
          }
        }

        // 设置推箱方向
        playerDirection.value = step.direction

        // 更新地图状态 - 移除原位置的箱子
        const fromCell = mapGrid.value[step.boxFrom.y][step.boxFrom.x]
        if (fromCell.type === 'box') {
          fromCell.type = 'floor'
          fromCell.char = '-'
        } else if (fromCell.type === 'boxOnTarget') {
          fromCell.type = 'target'
          fromCell.char = '.'
        }

        // 在新位置放置箱子
        const toCell = mapGrid.value[step.boxTo.y][step.boxTo.x]
        if (toCell.type === 'floor') {
          toCell.type = 'box'
          toCell.char = '$'
        } else if (toCell.type === 'target') {
          toCell.type = 'boxOnTarget'
          toCell.char = '*'
        }

        // 玩家推箱动作：移动到箱子原位置
        playerPos.value = { x: step.boxFrom.x, y: step.boxFrom.y }
        const playerCell = mapGrid.value[step.boxFrom.y][step.boxFrom.x]
        isOnTarget.value = playerCell.type === 'target'

        // 推箱动画延迟
        await new Promise(resolve => setTimeout(resolve, 80))
      }

      // 清除选中状态
      selectedBox.value = null
      boxMovePoints.value = []

      moves.value++
      isMoving.value = false

      // 检查是否通关
      if (checkLevelComplete()) {
        await handleLevelComplete()
      }
    }

    // 处理地图点击事件
    const handleCellClick = async (x, y) => {
      if (isMoving.value) return

      // 优先处理箱子点击
      if (selectBox(x, y)) {
        return
      }

      // 检查是否点击了箱子的可移动点
      if (selectedBox.value && isBoxMovePoint(x, y)) {
        await executePushBox(selectedBox.value.x, selectedBox.value.y, x, y)
        return
      }

      // 清除箱子选中状态（点击了其他位置）
      selectedBox.value = null
      boxMovePoints.value = []

      // 普通移动
      const path = findPath(playerPos.value.x, playerPos.value.y, x, y)
      if (path && path.length > 0) {
        await executeMove(path)
      }
    }

    // 获取基础地图格子样式（不包含玩家）
    const getBaseCellClass = (cell) => {
      const classes = ['game-cell']

      switch (cell.type) {
        case 'wall':
          classes.push('wall')
          break
        case 'box':
          classes.push('box')
          break
        case 'target':
          classes.push('target')
          break
        case 'boxOnTarget':
          classes.push('box-on-target')
          break
        case 'floor':
        default:
          classes.push('floor')
          break
      }

      return classes.join(' ')
    }

    // 获取基础地图格子的图片源（不包含叠加效果）
    const getBaseCellImageSrc = (cell) => {
      switch (cell.type) {
        case 'wall':
          return '../../assets/images/wall.png'
        case 'box':
          return '../../assets/images/box.png'
        case 'target':
          return '../../assets/images/target.png'
        case 'boxOnTarget':
          return '../../assets/images/box_on_target.png'
        case 'floor':
        default:
          return '../../assets/images/floor.png'
      }
    }

    // 获取玩家精灵样式类
    const getPlayerClass = () => {
      const classes = ['game-cell']

      if (isOnTarget.value) {
        classes.push('player-on-target', playerDirection.value)
      } else {
        classes.push('player', playerDirection.value)
      }

      return classes.join(' ')
    }

    // 获取玩家精灵的图片源
    const getPlayerImageSrc = () => {
      if (isOnTarget.value) {
        switch (playerDirection.value) {
          case 'left':
            return '../../assets/images/player_on_target_left.png'
          case 'up':
            return '../../assets/images/player_on_target_up.png'
          case 'right':
            return '../../assets/images/player_on_target_right.png'
          case 'down':
          default:
            return '../../assets/images/player_on_target_down.png'
        }
      } else {
        switch (playerDirection.value) {
          case 'left':
            return '../../assets/images/player_left.png'
          case 'up':
            return '../../assets/images/player_up.png'
          case 'right':
            return '../../assets/images/player_right.png'
          case 'down':
          default:
            return '../../assets/images/player_down.png'
        }
      }
    }

    // 获取玩家精灵位置样式
    const getPlayerStyle = () => {
      return {
        position: 'absolute',
        left: `${playerPos.value.x * 50 + 6}rpx`,  // 改为50rpx对应CSS
        top: `${playerPos.value.y * 50 + 6}rpx`,   // 改为50rpx对应CSS
        width: '50rpx',
        height: '50rpx',
        transition: isMoving.value ? 'all 0.08s ease-in-out' : 'none',
        zIndex: 10
      }
    }

    const getCellStyle = (cell) => {
      return {
        width: '50rpx',
        height: '50rpx'
      }
    }

    const gameBoardStyle = computed(() => {
      const maxWidth = mapGrid.value.length > 0 ? mapGrid.value[0].length : 0
      const maxHeight = mapGrid.value.length

      return {
        width: `${maxWidth * 50}rpx`,
        height: `${maxHeight * 50}rpx`
      }
    })

    const goBack = () => {
      try {
        const pages = Taro.getCurrentPages()
        console.log(pages)
        if (pages.length > 1) {
          Taro.navigateBack()
        } else {
          Taro.redirectTo({
            url: '/pages/index/index'
          })
        }
      } catch (error) {
        Taro.redirectTo({
          url: '/pages/index/index'
        })
      }
    }

    const resetLevel = () => {
      loadLevel(currentLevel.value)
    }

    return {
      currentLevel,
      levelData,
      mapGrid,
      moves,
      playerPos,
      playerDirection,
      isMoving,
      isOnTarget,
      selectedBox,
      boxMovePoints,
      isLevelComplete,
      gameBoardStyle,
      getBaseCellClass,
      getBaseCellImageSrc,
      getPlayerClass,
      getPlayerImageSrc,
      getPlayerStyle,
      getCellStyle,
      isBoxMovePoint,
      handleCellClick,
      goBack,
      resetLevel,
      customBarHeight
    }
  }
}
</script>